PostMessage API ব্যবহার করে নিরাপদ ক্রস-অরিজিন কমিউনিকেশন সম্পর্কে জানুন। এর ক্ষমতা, নিরাপত্তা ঝুঁকি এবং ওয়েব অ্যাপ্লিকেশনের দুর্বলতা মোকাবেলার সেরা উপায়গুলো শিখুন।
ক্রস-অরিজিন কমিউনিকেশন: PostMessage API-এর নিরাপত্তা প্যাটার্ন
আধুনিক ওয়েবে, অ্যাপ্লিকেশনগুলিকে প্রায়শই বিভিন্ন অরিজিন থেকে রিসোর্সের সাথে ইন্টারঅ্যাক্ট করতে হয়। সেম-অরিজিন পলিসি (SOP) একটি অত্যন্ত গুরুত্বপূর্ণ নিরাপত্তা ব্যবস্থা যা স্ক্রিপ্টগুলিকে একটি ভিন্ন অরিজিন থেকে রিসোর্স অ্যাক্সেস করতে বাধা দেয়। তবে, এমন কিছু বৈধ পরিস্থিতি রয়েছে যেখানে ক্রস-অরিজিন কমিউনিকেশন প্রয়োজন। postMessage API এটি অর্জনের জন্য একটি নিয়ন্ত্রিত ব্যবস্থা প্রদান করে, কিন্তু এর সম্ভাব্য নিরাপত্তা ঝুঁকি বোঝা এবং উপযুক্ত নিরাপত্তা প্যাটার্ন প্রয়োগ করা অত্যাবশ্যক।
সেম-অরিজিন পলিসি (SOP) বোঝা
সেম-অরিজিন পলিসি ওয়েব ব্রাউজারগুলির একটি মৌলিক নিরাপত্তা ধারণা। এটি ওয়েব পেজগুলিকে সেই ডোমেন ছাড়া অন্য কোনো ডোমেনে রিকোয়েস্ট পাঠানো থেকে বিরত রাখে যেখান থেকে ওয়েব পেজটি পরিবেশন করা হয়েছে। একটি অরিজিন স্কিম (প্রোটোকল), হোস্ট (ডোমেন) এবং পোর্ট দ্বারা সংজ্ঞায়িত করা হয়। যদি এর মধ্যে কোনোটি ভিন্ন হয়, তাহলে অরিজিনগুলো ভিন্ন বলে বিবেচিত হয়। উদাহরণস্বরূপ:
https://example.comhttps://www.example.comhttp://example.comhttps://example.com:8080
এই সবগুলি ভিন্ন ভিন্ন অরিজিন, এবং SOP এদের মধ্যে সরাসরি স্ক্রিপ্ট অ্যাক্সেস সীমাবদ্ধ করে।
PostMessage API-এর পরিচিতি
postMessage API ক্রস-অরিজিন কমিউনিকেশনের জন্য একটি নিরাপদ এবং নিয়ন্ত্রিত পদ্ধতি প্রদান করে। এটি স্ক্রিপ্টগুলিকে অন্য উইন্ডোতে (যেমন, iframe, নতুন উইন্ডো বা ট্যাব) তাদের অরিজিন নির্বিশেষে বার্তা পাঠাতে দেয়। গ্রহণকারী উইন্ডো তখন এই বার্তাগুলির জন্য অপেক্ষা করতে পারে এবং সেই অনুযায়ী প্রক্রিয়া করতে পারে।
একটি বার্তা পাঠানোর জন্য বেসিক সিনট্যাক্স হলো:
otherWindow.postMessage(message, targetOrigin);
otherWindow: টার্গেট উইন্ডোর একটি রেফারেন্স (যেমন,window.parent,iframe.contentWindow, অথবাwindow.openথেকে প্রাপ্ত একটি উইন্ডো অবজেক্ট)।message: আপনি যে ডেটা পাঠাতে চান। এটি যেকোনো জাভাস্ক্রিপ্ট অবজেক্ট হতে পারে যা সিরিয়ালাইজ করা যায় (যেমন, স্ট্রিং, সংখ্যা, অবজেক্ট, অ্যারে)।targetOrigin: আপনি যে অরিজিনে বার্তা পাঠাতে চান তা নির্দিষ্ট করে। এটি একটি অত্যন্ত গুরুত্বপূর্ণ নিরাপত্তা প্যারামিটার।
গ্রহণকারী প্রান্তে, আপনাকে message ইভেন্টের জন্য লিসেন করতে হবে:
window.addEventListener('message', function(event) {
// ...
});
event অবজেক্টটিতে নিম্নলিখিত প্রপার্টিগুলো থাকে:
event.data: অন্য উইন্ডো দ্বারা পাঠানো বার্তা।event.origin: যে উইন্ডো বার্তাটি পাঠিয়েছে তার অরিজিন।event.source: যে উইন্ডো বার্তাটি পাঠিয়েছে তার একটি রেফারেন্স।
নিরাপত্তা ঝুঁকি এবং দুর্বলতা
যদিও postMessage SOP সীমাবদ্ধতা এড়ানোর একটি উপায় সরবরাহ করে, তবে এটি সাবধানে প্রয়োগ না করা হলে সম্ভাব্য নিরাপত্তা ঝুঁকিও তৈরি করে। এখানে কিছু সাধারণ দুর্বলতা উল্লেখ করা হলো:
১. টার্গেট অরিজিনের অমিল
event.origin প্রপার্টি যাচাই করতে ব্যর্থ হওয়া একটি গুরুতর দুর্বলতা। যদি রিসিভার অন্ধভাবে বার্তাটিকে বিশ্বাস করে, তবে যেকোনো ওয়েবসাইট ক্ষতিকারক ডেটা পাঠাতে পারে। বার্তা প্রক্রিয়া করার আগে সর্বদা যাচাই করুন যে event.origin প্রত্যাশিত অরিজিনের সাথে মেলে।
উদাহরণ (দুর্বল কোড):
window.addEventListener('message', function(event) {
// DO NOT DO THIS!
processMessage(event.data);
});
উদাহরণ (সুরক্ষিত কোড):
window.addEventListener('message', function(event) {
if (event.origin !== 'https://trusted-origin.com') {
console.warn('Received message from untrusted origin:', event.origin);
return;
}
processMessage(event.data);
});
২. ডেটা ইনজেকশন
প্রাপ্ত ডেটা (event.data) এক্সিকিউটেবল কোড হিসেবে বিবেচনা করা বা সরাসরি DOM-এ ইনজেক্ট করা ক্রস-সাইট স্ক্রিপ্টিং (XSS) দুর্বলতার কারণ হতে পারে। এটি ব্যবহার করার আগে সর্বদা প্রাপ্ত ডেটা স্যানিটাইজ এবং যাচাই করুন।
উদাহরণ (দুর্বল কোড):
window.addEventListener('message', function(event) {
if (event.origin === 'https://trusted-origin.com') {
document.body.innerHTML = event.data; // DO NOT DO THIS!
}
});
উদাহরণ (সুরক্ষিত কোড):
window.addEventListener('message', function(event) {
if (event.origin === 'https://trusted-origin.com') {
const sanitizedData = sanitize(event.data); // Implement a proper sanitization function
document.getElementById('message-container').textContent = sanitizedData;
}
});
function sanitize(data) {
// Implement robust sanitization logic here.
// For example, use DOMPurify or a similar library
return DOMPurify.sanitize(data);
}
৩. ম্যান-ইন-দ্য-মিডল (MITM) অ্যাটাক
যদি একটি অসুরক্ষিত চ্যানেল (HTTP) এর মাধ্যমে যোগাযোগ হয়, তাহলে একজন MITM আক্রমণকারী বার্তাগুলিকে আটকাতে এবং পরিবর্তন করতে পারে। নিরাপদ যোগাযোগের জন্য সর্বদা HTTPS ব্যবহার করুন।
৪. ক্রস-সাইট রিকোয়েস্ট ফোরজারি (CSRF)
যদি রিসিভার সঠিক যাচাইকরণ ছাড়াই প্রাপ্ত বার্তার উপর ভিত্তি করে কোনো কাজ করে, তাহলে একজন আক্রমণকারী বার্তা জাল করে রিসিভারকে অনিচ্ছাকৃত কাজ করতে প্ররোচিত করতে পারে। CSRF সুরক্ষা ব্যবস্থা প্রয়োগ করুন, যেমন বার্তায় একটি গোপন টোকেন অন্তর্ভুক্ত করা এবং রিসিভারের দিকে এটি যাচাই করা।
৫. targetOrigin-এ ওয়াইল্ডকার্ড ব্যবহার করা
targetOrigin-কে *-এ সেট করলে যেকোনো অরিজিন বার্তাটি গ্রহণ করতে পারে। এটি একেবারে প্রয়োজনীয় না হলে এড়ানো উচিত, কারণ এটি অরিজিন-ভিত্তিক নিরাপত্তার উদ্দেশ্যকে ব্যর্থ করে দেয়। যদি আপনাকে অবশ্যই * ব্যবহার করতে হয়, তাহলে নিশ্চিত করুন যে আপনি অন্যান্য শক্তিশালী নিরাপত্তা ব্যবস্থা, যেমন মেসেজ অথেন্টিকেশন কোড (MACs) প্রয়োগ করেছেন।
উদাহরণ (এটি এড়িয়ে চলুন):
otherWindow.postMessage(message, '*'); // Avoid using '*' unless absolutely necessary
নিরাপত্তা প্যাটার্ন এবং সেরা অনুশীলন
postMessage-এর সাথে সম্পর্কিত ঝুঁকিগুলি হ্রাস করতে, নিম্নলিখিত নিরাপত্তা প্যাটার্ন এবং সেরা অনুশীলনগুলি অনুসরণ করুন:
১. কঠোর অরিজিন যাচাইকরণ
সর্বদা রিসিভারের দিকে event.origin প্রপার্টি যাচাই করুন। এটিকে বিশ্বস্ত অরিজিনের একটি পূর্বনির্ধারিত তালিকার সাথে তুলনা করুন। তুলনার জন্য কঠোর সমতা (===) ব্যবহার করুন।
২. ডেটা স্যানিটাইজেশন এবং যাচাইকরণ
postMessage-এর মাধ্যমে প্রাপ্ত সমস্ত ডেটা ব্যবহার করার আগে স্যানিটাইজ এবং যাচাই করুন। ডেটা কীভাবে ব্যবহার করা হবে তার উপর নির্ভর করে উপযুক্ত স্যানিটাইজেশন কৌশল ব্যবহার করুন (যেমন, HTML এস্কেপিং, URL এনকোডিং, ইনপুট ভ্যালিডেশন)। HTML স্যানিটাইজ করার জন্য DOMPurify-এর মতো লাইব্রেরি ব্যবহার করুন।
৩. মেসেজ অথেন্টিকেশন কোড (MACs)
বার্তার অখণ্ডতা এবং সত্যতা নিশ্চিত করতে একটি মেসেজ অথেন্টিকেশন কোড (MAC) অন্তর্ভুক্ত করুন। প্রেরক একটি শেয়ার করা গোপন কী ব্যবহার করে MAC গণনা করে এবং এটি বার্তায় অন্তর্ভুক্ত করে। প্রাপক একই শেয়ার করা গোপন কী ব্যবহার করে MAC পুনরায় গণনা করে এবং প্রাপ্ত MAC-এর সাথে তুলনা করে। যদি সেগুলি মেলে, তবে বার্তাটি খাঁটি এবং অপরিবর্তিত বলে বিবেচিত হয়।
উদাহরণ (HMAC-SHA256 ব্যবহার করে):
// প্রেরক
async function sendMessage(message, targetOrigin, sharedSecret) {
const encoder = new TextEncoder();
const data = encoder.encode(JSON.stringify(message));
const key = await crypto.subtle.importKey(
"raw",
encoder.encode(sharedSecret),
{ name: "HMAC", hash: "SHA-256" },
false,
["sign"]
);
const signature = await crypto.subtle.sign("HMAC", key, data);
const signatureArray = Array.from(new Uint8Array(signature));
const signatureHex = signatureArray.map(b => b.toString(16).padStart(2, '0')).join('');
const securedMessage = {
data: message,
signature: signatureHex
};
otherWindow.postMessage(securedMessage, targetOrigin);
}
// প্রাপক
async function receiveMessage(event, sharedSecret) {
if (event.origin !== 'https://trusted-origin.com') {
console.warn('Received message from untrusted origin:', event.origin);
return;
}
const securedMessage = event.data;
const message = securedMessage.data;
const receivedSignature = securedMessage.signature;
const encoder = new TextEncoder();
const data = encoder.encode(JSON.stringify(message));
const key = await crypto.subtle.importKey(
"raw",
encoder.encode(sharedSecret),
{ name: "HMAC", hash: "SHA-256" },
false,
["verify"]
);
const signature = await crypto.subtle.sign("HMAC", key, data);
const signatureArray = Array.from(new Uint8Array(signature));
const signatureHex = signatureArray.map(b => b.toString(16).padStart(2, '0')).join('');
if (signatureHex === receivedSignature) {
console.log('Message is authentic!');
processMessage(message); // বার্তাটি প্রক্রিয়া করা চালিয়ে যান
} else {
console.error('Message signature verification failed!');
}
}
গুরুত্বপূর্ণ: শেয়ার করা গোপন কী অবশ্যই সুরক্ষিতভাবে তৈরি এবং সংরক্ষণ করতে হবে। কোডে কী হার্ডকোড করা এড়িয়ে চলুন।
৪. নন্স এবং টাইমস্ট্যাম্প ব্যবহার করা
রিপ্লে অ্যাটাক প্রতিরোধ করতে, বার্তায় একটি অনন্য নন্স (একবার ব্যবহৃত সংখ্যা) এবং একটি টাইমস্ট্যাম্প অন্তর্ভুক্ত করুন। প্রাপক তখন যাচাই করতে পারে যে নন্সটি আগে ব্যবহার করা হয়নি এবং টাইমস্ট্যাম্পটি একটি গ্রহণযোগ্য সময়সীমার মধ্যে রয়েছে। এটি একজন আক্রমণকারীর পূর্বে আটকানো বার্তা পুনরায় পাঠানোর ঝুঁকি হ্রাস করে।
৫. সর্বনিম্ন বিশেষাধিকারের নীতি
অন্য উইন্ডোকে শুধুমাত্র ন্যূনতম প্রয়োজনীয় বিশেষাধিকার দিন। উদাহরণস্বরূপ, যদি অন্য উইন্ডোটির শুধুমাত্র ডেটা পড়ার প্রয়োজন হয়, তবে এটিকে ডেটা লেখার অনুমতি দেবেন না। আপনার কমিউনিকেশন প্রোটোকলটি সর্বনিম্ন বিশেষাধিকারের নীতি মাথায় রেখে ডিজাইন করুন।
৬. কনটেন্ট সিকিউরিটি পলিসি (CSP)
কোন উৎস থেকে স্ক্রিপ্ট লোড করা যাবে এবং স্ক্রিপ্টগুলি কী কী কাজ করতে পারবে তা সীমাবদ্ধ করতে কনটেন্ট সিকিউরিটি পলিসি (CSP) ব্যবহার করুন। এটি postMessage ডেটার ভুল ব্যবস্থাপনার ফলে উদ্ভূত XSS দুর্বলতার প্রভাব কমাতে সাহায্য করতে পারে।
৭. ইনপুট যাচাইকরণ
সর্বদা প্রাপ্ত ডেটার গঠন এবং বিন্যাস যাচাই করুন। একটি স্পষ্ট বার্তা বিন্যাস নির্ধারণ করুন এবং নিশ্চিত করুন যে প্রাপ্ত ডেটা এই বিন্যাসের সাথে সঙ্গতিপূর্ণ। এটি অপ্রত্যাশিত আচরণ এবং দুর্বলতা প্রতিরোধে সহায়তা করে।
৮. নিরাপদ ডেটা সিরিয়ালাইজেশন
বার্তা সিরিয়ালাইজ এবং ডিসিরিয়ালাইজ করার জন্য JSON এর মতো একটি নিরাপদ ডেটা সিরিয়ালাইজেশন ফরম্যাট ব্যবহার করুন। এমন ফরম্যাট ব্যবহার করা থেকে বিরত থাকুন যা কোড এক্সিকিউশনের অনুমতি দেয়, যেমন eval() বা Function()।
৯. বার্তার আকার সীমিত করুন
postMessage-এর মাধ্যমে পাঠানো বার্তার আকার সীমিত করুন। বড় বার্তা অতিরিক্ত রিসোর্স ব্যবহার করতে পারে এবং সম্ভাব্যভাবে ডিনায়াল-অফ-সার্ভিস আক্রমণের কারণ হতে পারে।
১০. নিয়মিত নিরাপত্তা নিরীক্ষা
সম্ভাব্য দুর্বলতা শনাক্ত এবং সমাধান করার জন্য আপনার কোডের নিয়মিত নিরাপত্তা নিরীক্ষা পরিচালনা করুন। postMessage-এর প্রয়োগের প্রতি বিশেষ মনোযোগ দিন এবং নিশ্চিত করুন যে সমস্ত নিরাপত্তা সেরা অনুশীলন অনুসরণ করা হচ্ছে।
উদাহরণ দৃশ্যকল্প: একটি Iframe এবং তার প্যারেন্টের মধ্যে নিরাপদ যোগাযোগ
এমন একটি পরিস্থিতি বিবেচনা করুন যেখানে https://iframe.example.com-এ হোস্ট করা একটি iframe-কে তার প্যারেন্ট পেজ https://parent.example.com-এর সাথে যোগাযোগ করতে হবে। iframe-টিকে প্রসেসিংয়ের জন্য প্যারেন্ট পেজে ব্যবহারকারীর ডেটা পাঠাতে হবে।
Iframe (https://iframe.example.com):
// একটি শেয়ার্ড সিক্রেট কী তৈরি করুন (একটি নিরাপদ কী জেনারেশন পদ্ধতি দিয়ে প্রতিস্থাপন করুন)
const sharedSecret = 'YOUR_SECURE_SHARED_SECRET';
// ব্যবহারকারীর ডেটা নিন
const userData = {
name: 'John Doe',
email: 'john.doe@example.com'
};
// প্যারেন্ট পেজে ব্যবহারকারীর ডেটা পাঠান
async function sendUserData(userData) {
const encoder = new TextEncoder();
const data = encoder.encode(JSON.stringify(userData));
const key = await crypto.subtle.importKey(
"raw",
encoder.encode(sharedSecret),
{ name: "HMAC", hash: "SHA-256" },
false,
["sign"]
);
const signature = await crypto.subtle.sign("HMAC", key, data);
const signatureArray = Array.from(new Uint8Array(signature));
const signatureHex = signatureArray.map(b => b.toString(16).padStart(2, '0')).join('');
const securedMessage = {
data: userData,
signature: signatureHex
};
parent.postMessage(securedMessage, 'https://parent.example.com');
}
sendUserData(userData);
প্যারেন্ট পেজ (https://parent.example.com):
// শেয়ার্ড সিক্রেট কী (iframe-এর কী-এর সাথে মিলতে হবে)
const sharedSecret = 'YOUR_SECURE_SHARED_SECRET';
window.addEventListener('message', async function(event) {
if (event.origin !== 'https://iframe.example.com') {
console.warn('Received message from untrusted origin:', event.origin);
return;
}
const securedMessage = event.data;
const userData = securedMessage.data;
const receivedSignature = securedMessage.signature;
const encoder = new TextEncoder();
const data = encoder.encode(JSON.stringify(userData));
const key = await crypto.subtle.importKey(
"raw",
encoder.encode(sharedSecret),
{ name: "HMAC", hash: "SHA-256" },
false,
["verify"]
);
const signature = await crypto.subtle.sign("HMAC", key, data);
const signatureArray = Array.from(new Uint8Array(signature));
const signatureHex = signatureArray.map(b => b.toString(16).padStart(2, '0')).join('');
if (signatureHex === receivedSignature) {
console.log('Message is authentic!');
// ব্যবহারকারীর ডেটা প্রক্রিয়া করুন
console.log('User data:', userData);
} else {
console.error('Message signature verification failed!');
}
});
গুরুত্বপূর্ণ নোট:
YOUR_SECURE_SHARED_SECRET-কে একটি সুরক্ষিতভাবে তৈরি করা শেয়ার্ড সিক্রেট কী দিয়ে প্রতিস্থাপন করুন।- শেয়ার্ড সিক্রেট কী অবশ্যই iframe এবং প্যারেন্ট পেজ উভয় ক্ষেত্রেই একই হতে হবে।
- এই উদাহরণটি মেসেজ অথেন্টিকেশনের জন্য HMAC-SHA256 ব্যবহার করে।
উপসংহার
postMessage API ওয়েব অ্যাপ্লিকেশনগুলিতে ক্রস-অরিজিন কমিউনিকেশন সক্ষম করার জন্য একটি শক্তিশালী টুল। তবে, সম্ভাব্য নিরাপত্তা ঝুঁকিগুলি বোঝা এবং এই ঝুঁকিগুলি হ্রাস করার জন্য উপযুক্ত নিরাপত্তা প্যাটার্ন প্রয়োগ করা অত্যন্ত গুরুত্বপূর্ণ। এই নির্দেশিকায় বর্ণিত নিরাপত্তা প্যাটার্ন এবং সেরা অনুশীলনগুলি অনুসরণ করে, আপনি শক্তিশালী এবং নিরাপদ ওয়েব অ্যাপ্লিকেশন তৈরি করতে নিরাপদে postMessage ব্যবহার করতে পারেন।
সর্বদা নিরাপত্তাকে অগ্রাধিকার দিতে মনে রাখবেন এবং ওয়েব ডেভেলপমেন্টের জন্য সর্বশেষ নিরাপত্তা সেরা অনুশীলনগুলির সাথে আপ-টু-ডেট থাকুন। আপনার অ্যাপ্লিকেশনগুলি সম্ভাব্য দুর্বলতা থেকে সুরক্ষিত আছে কিনা তা নিশ্চিত করতে নিয়মিত আপনার কোড এবং নিরাপত্তা কনফিগারেশন পর্যালোচনা করুন।